home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 1998 June
/
SGI Freeware 1998 June.iso
/
dist
/
fw_ATxgopher.idb
/
usr
/
freeware
/
src
/
xgopher.1.3
/
misc.c.z
/
misc.c
Wrap
C/C++ Source or Header
|
1998-01-21
|
11KB
|
492 lines
/* misc.c
miscellaneous utility functions. */
/*---------------------------------------------------------------*/
/* Xgopher version 1.3 08 April 1993 */
/* version 1.2 20 November 1992 */
/* version 1.1 20 April 1992 */
/* version 1.0 04 March 1992 */
/* X window system client for the University of Minnesota */
/* Internet Gopher System. */
/* Allan Tuchman, University of Illinois at Urbana-Champaign */
/* Computing and Communications Services Office */
/* Copyright 1992, 1993 by */
/* the Board of Trustees of the University of Illinois */
/* Permission is granted to freely copy and redistribute this */
/* software with the copyright notice intact. */
/*---------------------------------------------------------------*/
#include <stdio.h>
#include <sys/time.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "conf.h"
#include "gopher.h"
#include "globals.h"
#include "appres.h"
#include "itemList.h"
#include "dirList.h"
#include "misc.h"
#include "osdep.h"
/* timeNow
return the current time in some useful units, e.g., seconds. */
gopherTime
timeNow()
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
return tp.tv_sec;
}
/* timeSince
return the units (e.g., seconds) of time elapsed since the given time. */
gopherTime
timeSince(t)
gopherTime t;
{
struct timeval tp;
struct timezone tzp;
return (timeNow() - t);
}
/* setDirTime
set the creation time field on a gopher directory */
void
setDirTime(d)
gopherDirP d;
{
d->created = timeNow();
return;
}
/* clearDirWhenOld
cause a directory to be updated if it's creation time was a while ago. */
void
clearDirWhenOld(d)
gopherDirP d;
{
if (d == NULL || d == getCurrentDir()) return;
if (d->created == NOT_LOADED) return;
if (timeSince(d->created) > appResources->directoryTime) {
LOG(logFP, "Freeing old directory: %s\n",
USER_STRING(d->selectorItem));
freeItemList(&(d->contents));
d->created = NOT_LOADED;
}
return;
}
/* getTempFile
generate a temperary file name and return a pointer to it.
The caller should check for a NULL file pointer.
(The Unix routines mktemp(), tmpnam(), or tempnam() could be
used as the body of this routine.) */
void
getTempFile(tempName)
char *tempName;
{
static int fileCount = 0;
static int thisPID = 0;
if (thisPID == 0) thisPID = getpid();
sprintf (tempName, "%s/gop%d.%d",
tildePath(appResources->tempDirectory),
thisPID, fileCount++);
return;
}
/* These symbols are on most, but not all flavors of Unix, usually
in <sys/stat.h> or <sys/mode.h>. They are defined here just in
case they are missing. The symbols here are the POSIX names. */
#ifndef S_IWUSR
#ifdef S_IWRITE
#define S_IWUSR S_IWRITE /* write permission, owner */
#else /* !def S_IWRITE */
#define S_IWUSR 0000200 /* write permission, owner */
#endif /* def S_IWRITE */
#endif
#ifndef S_IWGRP
#define S_IWGRP 0000020 /* write permission, group */
#endif
#ifndef S_IWOTH
#define S_IWOTH 0000002 /* write permission, other */
#endif
/* isWriteableMode
return true if the given path name is that of an writable directory */
BOOLEAN
isWriteableMode(statBuf)
struct stat *statBuf;
{
int myUid, myGid;
if (statBuf->st_mode & S_IWOTH) {
return TRUE;
}
myGid = (int) getgid();
if ((statBuf->st_gid == myGid) && (statBuf->st_mode & S_IWGRP)) {
return TRUE;
}
myUid = (int) getuid();
if (statBuf->st_uid == myUid && statBuf->st_mode & S_IWUSR) {
return TRUE;
}
return FALSE;
}
/* These symbols are on most, but not all flavors of Unix, usually
in <sys/stat.h>. They are defined here just in case they are missing.
convex doesn't even have S_IEXEC. */
#ifndef S_IEXEC
#define S_IEXEC 0000100 /* execute/search permission, owner */
#endif
#ifndef S_IXGRP
#define S_IXGRP 0000010 /* execute/search permission, group */
#endif
#ifndef S_IXOTH
#define S_IXOTH 0000001 /* execute/search permission, other */
#endif
/* isExecutable
return true if the given path name is that of an executable file */
BOOLEAN
isExecutable(pathName)
char *pathName;
{
struct stat buf;
int myUid, myGid;
if (stat (pathName, &buf) != 0) return FALSE;
if (buf.st_mode & S_IXOTH) {
return TRUE;
}
myGid = (int) getgid();
if ((buf.st_gid == myGid) && (buf.st_mode & S_IXGRP)) {
return TRUE;
}
myUid = (int) getuid();
if (buf.st_uid == myUid && buf.st_mode & S_IEXEC) {
return TRUE;
}
return FALSE;
}
/* makeWordList
turn a string of words into a list of words, ignoring reserved words. */
char **
makeWordList(string)
char *string;
{
char *wordSpace;
char **word;
char *cp;
char *wp;
int next = 0;
int n = 0;
if (string == NULL) return NULL;
if ( ((wordSpace = malloc(INDEX_WORD_LEN)) == NULL) ||
((word = (char **) malloc(INDEX_WORD_COUNT * sizeof(char *))) ==
NULL) ) {
fprintf(stderr,
"Memory allocation error; trying to make index word list.\n");
fprintf(stderr,
"Recovery attempt by ignoring word list.\n");
return NULL;
}
cp = string;
while (*cp != '\0') {
while ((! isalnum(*cp)) && *cp != '\0' ) cp++;
if ( *cp == '\0' ) break;
wp = word[n] = &(wordSpace[next]);
while ( isalnum(*cp) ) {
*wp++ = isupper(*cp) ? tolower(*cp) : *cp;
cp++;
}
*wp = '\0';
if ( strcmp( word[n], "and") == 0 ||
strcmp(word[n], "not") == 0 ||
strcmp(word[n], "or") == 0) {
continue;
}
next = next + strlen( word[n]) + 1;
n++;
}
if (n == 0) {
free (wordSpace);
free (word);
return NULL;
}
word[n] = NULL;
return (word);
}
/* freeWordList
free a word list created by makeWordList. */
void
freeWordList(list)
char **list;
{
if (list != NULL && list[0] != NULL) {
free (list[0]);
free (list);
}
}
/* nextInPath
is an auxiliary function to support cmdPath (below) */
static char *
nextInPath (scan)
char **scan;
{
char *pc, *start;
/*---Null scan pointer says we are done---*/
if (*scan == 0) return(0);
/*---Advance scan pointer until ':' or '\0'---*/
for (pc=(*scan); (*pc != ':') &&
(*pc != '\0'); pc++) ;
/*---Remember where we started---*/
start = *scan;
/*---Did we get to the end of the path string?---*/
if (*pc == '\0') {
/*---Yes, tell the next time that we're done---*/
*scan = 0;
} else {
/*---No, make the ':' into a NULL (terminates returned string)
and advance next scan to char after ':'---*/
*pc = '\0';
*scan = pc+1;
}
return (start);
}
/* cmdPath
this code finds the path to an executable program using the user's
search path. If an absolute path name is provided, it is used.
Otherwise, we use envp to find the $PATH environment
variable; gets its value; then looks for the program name in
that path. The absolute path name of the first executable program
in the path is returned or NULL if none is found with execute
permission.
This routine is dependent on the Unix operating system. Mostly
because the notion of what constitutes an executable file is
OS specific. If you have porting problems, you can either rewrite
this routine or just specify absolute path names everywhere. */
char *
cmdPath (pgmName)
char *pgmName;
{
/* cmdPath uses stat(2) to look for the executable file by trying
each directory in the users path. Each time that fails, try the
next directory in the path. The first time it succeeds, return
the path. If the name is not found at all in the path, then
return NULL. */
char path[PATH_NAME_LEN], tempbuf[PATH_NAME_LEN];
char *scan, *dir;
char *name, *pathVar;
struct stat buf;
char *absPathName = (char *) malloc (PATH_NAME_LEN);
/* according to the man page for sh(1), if the command name
contains a '/', then the $path variable is not searched. */
if (index (pgmName, '/')) {
strcpy (absPathName, pgmName);
return (absPathName);
} else {
if (((pathVar = getenv ("PATH")) == NULL) ||
(*pathVar == '\0')) {
strcpy (absPathName, "./");
strcat (absPathName, pgmName);
return (absPathName);
}
strncpy (path, pathVar, PATH_NAME_LEN);
*absPathName = '\0';
scan = path;
while( (dir = nextInPath (&scan)) != 0 ) {
strncpy (tempbuf, dir, PATH_NAME_LEN);
strcat (tempbuf, "/");
name = strcat (tempbuf, pgmName);
if (isExecutable(name)) {
strcpy (absPathName, name);
return (absPathName);
}
}
return (NULL);
}
}
#include <pwd.h>
/* tildePath
expand a leading "~/" on a pathname to be the value of $HOME/.
The value returned is a pointer to static storage and must
be copied by the caller to preserve it. If there is no leading "~/",
then the input pathname is copied to the static storage. */
char *
tildePath(path)
char *path;
{
char *home;
static char newPath[PATH_NAME_LEN];
*newPath = '\0';
if (path != NULL) {
if (*path == '~') {
if (*(path+1) == '/' || *(path+1) == NULLC) {
if ((home = getenv("HOME")) != NULL) {
strcpy(newPath, home);
}
path++;
} else {
char *slash = index (path+1, '/');
struct passwd *pwdentry;
if (slash != NULL) {
*slash = '\0';
if ((pwdentry = getpwnam(path+1)) != NULL) {
strcpy(newPath, pwdentry->pw_dir);
path = slash;
}
*slash = '/';
} else {
if ((pwdentry = getpwnam(path+1)) != NULL) {
strcpy(newPath, pwdentry->pw_dir);
path += strlen(path);
}
}
}
}
strcat(newPath, path);
}
return newPath;
}
/* vStringSet
set the value of a variable length string, length and data.
This routine was inspired by those in STRstring.* from the
gopher Unix client, version 0.9. The main reason for changing
them at all is that the chosen data type name in the original
routines, String, conflicts with the X Window System data
type of the same name, but different type.
For our purposes it is not worth allocating less than 128
bytes. The primary use is for selector strings. These will
generally grow , but eventually stabalize around 100 bytes.
Except for WAIS searches, when they will grow REALLY big. */
void vStringSet(vs, value)
vString *vs;
char *value;
{
int need;
if (value == NULL) return;
if (*value == '\0')
need = 1;
else
need = strlen(value) + 1;
if (vs->data == NULL) {
if (need < 128) need = 128;
if ((vs->data = malloc (need * sizeof(char *))) == NULL) {
fprintf (stderr,
"Cannot allocate more memory for a string.");
exit(1);
}
strcpy (vs->data, value);
vs->len = need;
} else {
if (vs->len >= need)
strcpy(vs->data, value);
else {
if ((vs->data = realloc(vs->data, need)) == NULL) {
fprintf (stderr,
"Cannot allocate more memory for a string.");
exit(1);
}
strcpy(vs->data, value);
vs->len = need;
}
}
}